import sys
import threading
import time
from typing import Optional

import numpy as np
import pygame

from player.AlphaZeroPlayer import MCTSPlayer
from player.ComparePlayer import ComparePlayer
from player.base.player import Player


class Game():

    def __init__(self, white_player: Optional[Player], black_player: Optional[Player], chess):
        self.white_player = white_player
        self.white_player.set_playinfo(2, '白棋')
        self.black_player = black_player
        self.black_player.set_playinfo(1, '黑棋')
        self.chess = chess
        self.win: bool = False
        self.down_pos = []
        pygame.init()

    def play(self):
        threading.Thread(target=self.async_step).start()

        # 主循环
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

            self.chess.fill()
            # 绘制棋盘
            self.chess.draw_board()
            # 更新显示
            pygame.display.flip()

    def down_piece(self, pos, player):
        board = self.chess.get_board().tolist()
        code = 0

        while True:
            step = player.step(board, pos, code, self.down_pos)
            if self.chess.down_piece(step, player.user):
                self.down_pos.append(step)
                break
            print('当前下棋位置已有其他棋子请重新落子')
            code = 2

        win = self.isWin(step)
        if win:
            if win == 1:
                print('%s获胜!' % player.get_name())
                self.win = True
            elif win == 2:
                print('平手')
                self.win = True


        return step

    # 思路：在pos位置竖直、横直、左斜、右斜，正负方向连续搜索计数
    def isWin(self, pos):
        """判断某位置是否连成五子"""
        board = self.chess.get_board()

        if np.all(board != 0):
            print('平手')
            return 2

        x, y = pos
        player = board[x][y]

        directions = [(1, 0), (0, 1), (1, 1), (1, -1)]
        for dx, dy in directions:
            count = [(x, y)]  # 当前方向的连续棋子计数

            # 在负方向查找
            nx, ny = x - dx, y - dy
            while 0 <= nx < self.chess.GRID_SIZE and 0 <= ny < self.chess.GRID_SIZE and board[nx][ny] == player:
                count.append((nx, ny))
                nx -= dx
                ny -= dy

            # 在正方向查找
            nx, ny = x + dx, y + dy
            while 0 <= nx < self.chess.GRID_SIZE and 0 <= ny < self.chess.GRID_SIZE and board[nx][ny] == player:
                count.append((nx, ny))
                nx += dx
                ny += dy

            # 如果在一个方向上总计连续棋子达到 5 个，返回 True 表示获胜
            if len(count) >= 5:
                self.chess.set_win(count)
                self.chess.current_pos = None
                return 1

        return 0

    def async_step(self):
        pos = None
        while not self.win:
            pos = self.down_piece(pos, self.black_player)
            time.sleep(1)
            if self.win:
                break
            pos = self.down_piece(pos, self.white_player)
            time.sleep(1)
